package moe.codeest.enviews;


import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.*;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;

/**
 * Created by codeest on 16/11/7.
 * <p>
 * 论如何从直线到曲线再到三角形 =。=
 */

public class ENPlayView extends Component implements Component.DrawTask, Component.LayoutRefreshedListener {

    public static int STATE_PLAY = 0;

    public static int STATE_PAUSE = 1;

    public static int DEFAULT_LINE_COLOR = 0xffffffff;

    public static int DEFAULT_BG_LINE_COLOR = 0xff444a4f;

    public static int DEFAULT_LINE_WIDTH = 14;

    public static int DEFAULT_BG_LINE_WIDTH = 12;

    public static int DEFAULT_DURATION = 1200;

    private int mCurrentState = STATE_PAUSE;

    private Paint mPaint, mBgPaint;

    private int mWidth, mHeight;

    private int mCenterX, mCenterY;

    private int mCircleRadius;

    private RectFloat mRectF, mBgRectF;

    private float mFraction = 1;

    private Path mPath, mDstPath;

    private PathMeasure mPathMeasure;

    private float mPathLength;

    private int mDuration;

    private boolean isInit = false;

    public ENPlayView(Context context) {
        this(context, null);
    }

    public ENPlayView(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    public ENPlayView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        int lineColor = AttrUtils.getColorFromAttr(attrSet, "play_line_color", DEFAULT_LINE_COLOR);
        int bgLineColor = AttrUtils.getColorFromAttr(attrSet, "play_bg_line_color", DEFAULT_BG_LINE_COLOR);
        int lineWidth = AttrUtils.getDimensionFromAttr(attrSet, "play_line_width", DEFAULT_LINE_WIDTH);
        int bgLineWidth = AttrUtils.getDimensionFromAttr(attrSet, "play_bg_line_width", DEFAULT_BG_LINE_WIDTH);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE_STYLE);
        mPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
        mPaint.setColor(new Color(lineColor));
        mPaint.setStrokeWidth(lineWidth);
        mPaint.setPathEffect(new PathEffect(1));

        mBgPaint = new Paint();
        mBgPaint.setAntiAlias(true);
        mBgPaint.setStyle(Paint.Style.STROKE_STYLE);
        mBgPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
        mBgPaint.setColor(new Color(bgLineColor));
        mBgPaint.setStrokeWidth(bgLineWidth);

        mPath = new Path();
        mDstPath = new Path();
        mPathMeasure = new PathMeasure(mPath, false);

        mDuration = DEFAULT_DURATION;

        addDrawTask(this);
        setLayoutRefreshedListener(this);
    }

    public void setLineColor(int color) {
        mPaint.setColor(new Color(color));
        invalidate();
    }

    public void setBgLineColor(int color) {
        mBgPaint.setColor(new Color(color));
        invalidate();
    }

    public void setLineWidth(int lineWidth) {
        mPaint.setStrokeWidth(lineWidth);
        invalidate();
    }

    public void setBgLineWidth(int bgLineWidth) {
        mBgPaint.setStrokeWidth(bgLineWidth);
        invalidate();
    }


    @Override
    public void onRefreshed(Component component) {
        mWidth = component.getWidth() * 9 / 10;
        mHeight = component.getHeight() * 9 / 10;
        mCircleRadius = mWidth / 10;
        mCenterX = component.getWidth() / 2;
        mCenterY = component.getHeight() / 2;
        mRectF = new RectFloat(mCenterX - mCircleRadius, mCenterY + 0.6f * mCircleRadius,
                mCenterX + mCircleRadius, mCenterY + 2.6f * mCircleRadius);
        mBgRectF = new RectFloat(mCenterX - mWidth / 2, mCenterY - mHeight / 2, mCenterX + mWidth / 2, mCenterY + mHeight / 2);
        mPath.moveTo(mCenterX - mCircleRadius, mCenterY + 1.8f * mCircleRadius);
        mPath.lineTo(mCenterX - mCircleRadius, mCenterY - 1.8f * mCircleRadius);
        mPath.lineTo(mCenterX + mCircleRadius, mCenterY);
        mPath.close();
        mPathMeasure.setPath(mPath, false);
        mPathLength = mPathMeasure.getLength();
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (!isInit) {
            isInit = true;
            onRefreshed(component);
        }
        canvas.drawCircle(mCenterX, mCenterY, mWidth / 2, mBgPaint);
        if (mFraction < 0) {    //嗷~~ 弹性部分
            canvas.drawLine(mCenterX + mCircleRadius, mCenterY - 1.6f * mCircleRadius + 10 * mCircleRadius * mFraction,
                    mCenterX + mCircleRadius, mCenterY + 1.6f * mCircleRadius + 10 * mCircleRadius * mFraction, mPaint);

            canvas.drawLine(mCenterX - mCircleRadius, mCenterY - 1.6f * mCircleRadius,
                    mCenterX - mCircleRadius, mCenterY + 1.6f * mCircleRadius, mPaint);

            canvas.drawArc(mBgRectF, new Arc(-105, 360, false), mPaint);
        } else if (mFraction <= 0.3) {  //嗷~~ 右侧直线和下方曲线
            canvas.drawLine(mCenterX + mCircleRadius, mCenterY - 1.6f * mCircleRadius + mCircleRadius * 3.2f / 0.3f * mFraction,
                    mCenterX + mCircleRadius, mCenterY + 1.6f * mCircleRadius, mPaint);

            canvas.drawLine(mCenterX - mCircleRadius, mCenterY - 1.6f * mCircleRadius,
                    mCenterX - mCircleRadius, mCenterY + 1.6f * mCircleRadius, mPaint);

            if (mFraction != 0)
                canvas.drawArc(mRectF, new Arc(0f, 180f / 0.3f * mFraction, false), mPaint);

            canvas.drawArc(mBgRectF, new Arc(-105 + 360 * mFraction, 360 * (1 - mFraction), false), mPaint);
        } else if (mFraction <= 0.6) {  //嗷~~ 下方曲线和三角形
            canvas.drawArc(mRectF, new Arc(180f / 0.3f * (mFraction - 0.3f), 180 - 180f / 0.3f * (mFraction - 0.3f), false), mPaint);

            mDstPath.reset();
            mPathMeasure.getSegment(0.02f * mPathLength, 0.38f * mPathLength + 0.42f * mPathLength / 0.3f * (mFraction - 0.3f),
                    mDstPath, true);
            canvas.drawPath(mDstPath, mPaint);

            canvas.drawArc(mBgRectF, new Arc(-105 + 360 * mFraction, 360 * (1 - mFraction), false), mPaint);
        } else if (mFraction <= 0.8) {  //嗷~~ 三角形
            mDstPath.reset();
            mPathMeasure.getSegment(0.02f * mPathLength + 0.2f * mPathLength / 0.2f * (mFraction - 0.6f)
                    , 0.8f * mPathLength + 0.2f * mPathLength / 0.2f * (mFraction - 0.6f),
                    mDstPath, true);
            canvas.drawPath(mDstPath, mPaint);

            canvas.drawArc(mBgRectF, new Arc(-105 + 360 * mFraction, 360 * (1 - mFraction), false), mPaint);
        } else {    //嗷~~ 弹性部分
            mDstPath.reset();
            mPathMeasure.getSegment(10 * mCircleRadius * (mFraction - 1)
                    , mPathLength,
                    mDstPath, true);
            canvas.drawPath(mDstPath, mPaint);
        }
    }

    public void play() {
        if (mCurrentState == STATE_PLAY) {
            return;
        }
        mCurrentState = STATE_PLAY;
        AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setDuration(mDuration);
        animatorValue.setCurveType(Animator.CurveType.ANTICIPATE);
        animatorValue.setValueUpdateListener((animatorValue1, v) -> {
            mFraction = 1 - v;
            invalidate();
        });
        animatorValue.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {

            }

            @Override
            public void onStop(Animator animator) {

            }

            @Override
            public void onCancel(Animator animator) {

            }

            @Override
            public void onEnd(Animator animator) {
                mFraction = 0;
                invalidate();
            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        });
        if (!animatorValue.isRunning()) {
            animatorValue.start();
        }
    }

    public void pause() {
        if (mCurrentState == STATE_PAUSE) {
            return;
        }
        mCurrentState = STATE_PAUSE;
        AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setDuration(mDuration);
        animatorValue.setCurveType(Animator.CurveType.ANTICIPATE);
        animatorValue.setValueUpdateListener((animatorValue1, v) -> {
            mFraction = v;
            invalidate();
        });
        animatorValue.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {

            }

            @Override
            public void onStop(Animator animator) {

            }

            @Override
            public void onCancel(Animator animator) {

            }

            @Override
            public void onEnd(Animator animator) {
                mFraction = 1;
                invalidate();
            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        });
        if (!animatorValue.isRunning()) {
            animatorValue.start();
        }
    }

    public int getCurrentState() {
        return mCurrentState;
    }

    public void setDuration(int duration) {
        mDuration = duration;
    }
}
